package com.roy.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
/**
 * 启动后浏览器访问8081端口
 */
public class NioServer {
	private Selector selector;
	
	public void init() throws IOException {
		this.selector = Selector.open();//创建选择器
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();//创建服务器渠道
		
		serverSocketChannel.bind(new InetSocketAddress(8081));
		serverSocketChannel.configureBlocking(false);//非阻塞
		System.out.println("NIO服务器已启动，绑定端口 8081");
		ServerSocket serverSocket = serverSocketChannel.socket();
		//注册事件。
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
	}

	public void start() throws IOException {
		while(true) {
			//如果有请求过来 可能有多个.这一步是阻塞的。
			selector.select();
			//遍历多个事件
			Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
			while(iterator.hasNext()) {
				SelectionKey selectionKey = iterator.next();
				iterator.remove();
				if(selectionKey.isAcceptable()) {//请求事件
					accept(selectionKey);
				}else if(selectionKey.isReadable()) {//读事件
					read(selectionKey);
				}
			}
		}
		
	}
	//连接时间
	public void accept(SelectionKey key) throws IOException {
		ServerSocketChannel serverSocketChannel = (ServerSocketChannel)key.channel();
		SocketChannel channel = serverSocketChannel.accept();
		channel.configureBlocking(false);//设置非堵塞
		//注册读事件
		channel.register(selector, SelectionKey.OP_READ);
	}
	//IO处理
	public void read(SelectionKey key) throws IOException {
		SocketChannel socketChannel = (SocketChannel)key.channel();
		ByteBuffer byteBuffer = ByteBuffer.allocate(1024);//分配缓冲区
		socketChannel.read(byteBuffer);//读入缓存
		String request = new String(byteBuffer.array()).trim();
		System.out.println("客户端请求："+request);
//		客户端请求：GET /favicon.ico HTTP/1.1
//		Host: localhost:8081
//		Connection: keep-alive
//		User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
//		Accept: image/webp,image/apng,image/*,*/*;q=0.8
//		Referer: http://localhost:8081/?p=123456
//		Accept-Encoding: gzip, deflate, br
//		Accept-Language: zh-CN,zh;q=0.9
//		Cookie: _ga=GA1.1.457360742.1541141586; _xsrf=2|1050f3cb|31ed3f8f31403c6e20c1bf537afcdddf|1548056232; username-localhost-8888="2|1:0|10:1548149646|23:username-localhost-8888|44:MzIzNGZhNGVjM2E2NDM3NDk3YWEzMDNmYThmMDZjZmY=|d2b6ec4c7a91fef38ef5210be5c78175d79a3b107f4c61e6f234344196a335c2"; _gid=GA1.1.1037098623.1548665120
		String outputString = "HTTP/1.1 200 OK\n Content-Type: text/html; charset=UTF-8\n\n"
				+"<html><head><title>nio-demo</title></head><body><h1>NIO--DEMO</h1></body></html>";
		ByteBuffer outBuffer = ByteBuffer.wrap(outputString.getBytes());
		socketChannel.write(outBuffer);
		socketChannel.close();
		
	}
	public static void main(String[] args) throws IOException {
		NioServer server = new NioServer();
		server.init();
		server.start();
	}
}
